using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections;
using System.Collections.ObjectModel;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;

namespace VSSAHT.Transfer
{
    //[DataContract]
    [Serializable]
    public abstract class DTOBase
    {
        #region Properties use in progress

        /// <summary>
        /// Creating status
        /// </summary>
        [NonSerialized]
        private bool _isNew = false;
        public bool IsNew
        {
            get { return _isNew; }
            set
            {
                if (_isNew != value)
                {
                    OnIsNewChanging(value);
                    _isNew = value;
                    OnIsNewChanged();
                }
            }
        }

        /// <summary>
        /// Editing status
        /// </summary>
        [NonSerialized]
        private bool _isEdited = false;
        public bool IsEdited
        {
            get { return _isEdited; }
            set
            {
                if (_isEdited != value)
                {
                    OnIsEditChanging(value);
                    _isEdited = value;
                    OnIsEditChanged();
                }
            }
        }

        /// <summary>
        /// Deleted status
        /// </summary>
        [NonSerialized]
        private bool _isRemove = false;
        public bool IsRemove
        {
            get { return _isRemove; }
            set
            {
                if (_isRemove != value)
                {
                    OnIsDeleteChanging(value);
                    _isRemove = value;
                    OnIsDeleteChanged();
                }
            }
        }

        /// <summary>
        /// Checked status
        /// </summary>
        [NonSerialized]
        private bool _isChecked = false;
        public bool IsChecked
        {
            get { return _isChecked; }
            set
            {
                if (_isChecked != value)
                {
                    OnIsCheckedChanging(value);
                    _isChecked = value;
                    OnIsCheckedChanged();
                }
            }
        }

        /// <summary>
        /// Selected status
        /// </summary>
        [NonSerialized]
        private bool _isSelected = false;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected != value)
                {
                    OnIsSelectedChanging(value);
                    _isSelected = value;
                    OnIsSelectedChanged();
                }
            }
        }

        /// <summary>
        /// IsError status
        /// </summary>
        [NonSerialized]
        private bool _isError = false;
        public bool IsError
        {
            get { return _isError; }
            set
            {
                if (_isError != value)
                {
                    OnIsErrorChanging(value);
                    _isError = value;
                    OnIsErrorChanged();
                }
            }
        }

        //public bool? ThreeState
        //{
        //    get
        //    {
        //        if (_isNew)
        //            return true;
        //        if (_isEdited)
        //            return false;
        //        return null;
        //    }
        //}

        #endregion

        #region Methods

        #region Extension Methods

        protected virtual void OnIsNewChanging(object value) { }
        protected virtual void OnIsNewChanged() { }

        protected virtual void OnIsEditChanging(object value) { }
        protected virtual void OnIsEditChanged() { }

        protected virtual void OnIsDeleteChanging(object value) { }
        protected virtual void OnIsDeleteChanged() { }

        protected virtual void OnIsCheckedChanging(object value) { }
        protected virtual void OnIsCheckedChanged() { }

        protected virtual void OnIsSelectedChanging(object value) { }
        protected virtual void OnIsSelectedChanged() { }

        protected virtual void OnIsErrorChanging(object value) { }
        protected virtual void OnIsErrorChanged() { }

        #endregion

        #region Change IsEdit

        protected virtual void OnChanged()
        {
            if (!IsEdited) IsEdited = true;
        }

        #endregion

        #region DeepClone
        /// <summary>
        /// Perform a deep Copy of the object.
        /// </summary>
        /// <typeparam name="T">The type of object being copied.</typeparam>
        /// <param name="source">The object instance to copy.</param>
        /// <returns>The copied object.</returns>
        public static T Clone<T>(T source)
        {
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable.", "source");
            }

            // Don't serialize a null object, simply return the default for that object
            if (Object.ReferenceEquals(source, null))
            {
                return default(T);
            }

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }

        /// Perform a deep Copy of the object.
        /// </summary>
        /// <typeparam name="T">The type of object being copied.</typeparam>
        /// <param name="source">The object instance to copy.</param>
        /// <returns>The copied object.</returns>
        public static void CopyTo<T>(T source, T target)
        {
            target = DTOBase.Clone<T>(source);
        }

        #endregion

        protected string CutWords(string originalString, int numberChars)
        {
            string[] arrayString = originalString.Split(' ');
            if (arrayString.Count() > numberChars)
            {
                return String.Join(" ", arrayString, 0, numberChars) + " ...";
            }
            else
                return originalString;
        }

        #endregion
    }
}
